package com.yy.task;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yy.domain.SecondHospitalAppointmentsDO;
import com.yy.enums.Status;
import com.yy.enums.TaskRange;
import com.yy.enums.TaskStatus;
import com.yy.service.SecondHospitalAppointmentsService;
import com.yy.vo.DoctorInfoRequestVO;
import com.yy.vo.ImageRequestVO;
import com.yy.vo.ScheduleRequestVO;
import com.yy.vo.WeekScheduleReqBoVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @Description:
 * @ClassName: MultiThreadTask
 * @author: 姚欣宏
 * @date: 2023.07.11
 */
@EnableScheduling   // 1.开启定时任务
//@EnableAsync        // 2.开启多线程
@Component
@Slf4j
public class SecondThreadTask {
    private final SecondHospitalAppointmentsService secondHospitalAppointmentsService;

    public SecondThreadTask(SecondHospitalAppointmentsService secondHospitalAppointmentsService) {
        this.secondHospitalAppointmentsService = secondHospitalAppointmentsService;
    }


    @Value("${serverValue}")
    private Integer SERVER;

    @Value("${imagesValue}")
    private Integer IMAGES;


    @Scheduled(cron = "0 0 7 * * ?")
    public void morningShiftSchedule() {
        String dateStr = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        QueryWrapper<SecondHospitalAppointmentsDO> wrapper = new QueryWrapper<>();
        wrapper.eq("server", SERVER).eq("task_status", TaskStatus.PENDING_SCHEDULE_RETRIEVAL.getCode()).eq("status", Status.AUTOMATIC.getCode()).apply("date_format(appointment_date, '%Y-%m-%d') = {0}", dateStr).eq("appointment_range", TaskRange.MORNING.getCode());
        List<SecondHospitalAppointmentsDO> appointmentTasksDOList = secondHospitalAppointmentsService.list(wrapper);
        if (CollUtil.isNotEmpty(appointmentTasksDOList)) {
            schedule(appointmentTasksDOList);
            log.info(dateStr + TaskRange.MORNING.getDescription() + "排班执行完毕");
        }
    }

    private void schedule(List<SecondHospitalAppointmentsDO> appointmentTasksDOList) {
        appointmentTasksDOList.forEach(v -> {
            DoctorInfoRequestVO doctorInfoRequestVO = new DoctorInfoRequestVO();
            doctorInfoRequestVO.setId(v.getId());
            doctorInfoRequestVO.setDoctorId(v.getDoctorId());
            secondHospitalAppointmentsService.selDoctorSchedule(doctorInfoRequestVO);
        });
    }

    @Scheduled(cron = "0 58 7 * * ?")
    public void morningVerificationCode() {
        String dateStr = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        QueryWrapper<SecondHospitalAppointmentsDO> wrapper = new QueryWrapper<>();
        wrapper.eq("server", SERVER).eq("task_status", TaskStatus.PENDING_INITIATION.getCode()).eq("status", Status.AUTOMATIC.getCode()).apply("date_format(appointment_date, '%Y-%m-%d') = {0}", dateStr).eq("appointment_range", TaskRange.MORNING.getCode());
        List<SecondHospitalAppointmentsDO> appointmentTasksDOList = secondHospitalAppointmentsService.list(wrapper);
        if (CollUtil.isNotEmpty(appointmentTasksDOList)) {
            imageCode(appointmentTasksDOList);
            log.info(dateStr + TaskRange.MORNING.getDescription() + "验证码执行完毕");
        }

    }

    private void imageCode(List<SecondHospitalAppointmentsDO> appointmentTasksDOList) {
        appointmentTasksDOList.forEach(v -> {
            for (int i = 0; i < IMAGES; i++) {
                ImageRequestVO imageRequestVO = new ImageRequestVO();
                imageRequestVO.setId(v.getId());
                secondHospitalAppointmentsService.getImageCode(imageRequestVO);
                try {
                    Thread.sleep(1000); // 1秒钟，单位为毫秒
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    @Scheduled(cron = "0 0 8 * * ?")
    public void morningNumberGrabbing() {
        String dateStr = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        QueryWrapper<SecondHospitalAppointmentsDO> wrapper = new QueryWrapper<>();
        wrapper.eq("server", SERVER).eq("task_status", TaskStatus.PENDING_INITIATION.getCode()).eq("status", Status.AUTOMATIC.getCode()).apply("date_format(appointment_date, '%Y-%m-%d') = {0}", dateStr).eq("appointment_range", TaskRange.MORNING.getCode());
        List<SecondHospitalAppointmentsDO> appointmentTasksDOList = secondHospitalAppointmentsService.list(wrapper);
        if (CollUtil.isNotEmpty(appointmentTasksDOList)) {
            threadAPP(appointmentTasksDOList);
            // 所有子线程的任务都已经执行完毕，执行主线程的代码
            log.info(dateStr + TaskRange.MORNING.getDescription() + "下单执行完毕");
        }
    }

    private void threadAPP(List<SecondHospitalAppointmentsDO> appointmentTasksDOList) {
        ExecutorService touchWorker = Executors.newFixedThreadPool(5);
        long start = System.currentTimeMillis();
        for (SecondHospitalAppointmentsDO SecondHospitalAppointmentsDO : appointmentTasksDOList) {
            touchWorker.execute(() -> secondHospitalAppointmentsService.autoSureAppointment(SecondHospitalAppointmentsDO));//让线程池执行工作
        }
        touchWorker.shutdown();//关闭线程池
        while (true) {
            if (touchWorker.isTerminated()) {
                break;
            }
        }
        long end = System.currentTimeMillis();
        System.out.println((end - start) / 1000);
    }


    @Scheduled(cron = "0 50 19 * * ?")
    public void eveningShiftSchedule() {
        String dateStr = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        QueryWrapper<SecondHospitalAppointmentsDO> wrapper = new QueryWrapper<>();
        wrapper.eq("server", SERVER).eq("task_status", TaskStatus.PENDING_SCHEDULE_RETRIEVAL.getCode()).eq("status", Status.AUTOMATIC.getCode()).apply("date_format(appointment_date, '%Y-%m-%d') = {0}", dateStr).eq("appointment_range", TaskRange.AFTERNOON.getCode());
        List<SecondHospitalAppointmentsDO> appointmentTasksDOList = secondHospitalAppointmentsService.list(wrapper);
        if (CollUtil.isNotEmpty(appointmentTasksDOList)) {
            schedule(appointmentTasksDOList);
            log.info(dateStr + TaskRange.AFTERNOON.getDescription() + "排班执行完毕");
        }
    }

    @Scheduled(cron = "57 59 19 * * ?")
    public void eveningVerificationCode() {
        String dateStr = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        QueryWrapper<SecondHospitalAppointmentsDO> wrapper = new QueryWrapper<>();
        wrapper.eq("server", SERVER).eq("task_status", TaskStatus.PENDING_INITIATION.getCode()).eq("status", Status.AUTOMATIC.getCode()).apply("date_format(appointment_date, '%Y-%m-%d') = {0}", dateStr).eq("appointment_range", TaskRange.AFTERNOON.getCode());
        List<SecondHospitalAppointmentsDO> appointmentTasksDOList = secondHospitalAppointmentsService.list(wrapper);
        if (CollUtil.isNotEmpty(appointmentTasksDOList)) {
            imageCode(appointmentTasksDOList);
            log.info(dateStr + TaskRange.AFTERNOON.getDescription() + "验证码执行完毕");
        }

    }

    @Scheduled(cron = "${scheduled.nightCron}")
    public void eveningNumberGrabbing() {
        String dateStr = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        QueryWrapper<SecondHospitalAppointmentsDO> wrapper = new QueryWrapper<>();
        wrapper.eq("server", SERVER).eq("task_status", TaskStatus.PENDING_INITIATION.getCode()).eq("status", Status.AUTOMATIC.getCode()).apply("date_format(appointment_date, '%Y-%m-%d') = {0}", dateStr).eq("appointment_range", TaskRange.AFTERNOON.getCode());
        List<SecondHospitalAppointmentsDO> appointmentTasksDOList = secondHospitalAppointmentsService.list(wrapper);
        if (CollUtil.isNotEmpty(appointmentTasksDOList)) {
            threadAPP(appointmentTasksDOList);
            // 所有子线程的任务都已经执行完毕，执行主线程的代码
            log.info(dateStr + TaskRange.AFTERNOON.getDescription() + "下单执行完毕");
        }
    }
}



